<?php
/*
 * 采用简单工厂的优点是可以使用户根据参数获得对应的类实例，避免了直接实例化类，降低了耦合性；
 * 缺点是可实例化的类型在编译期间已经被确定，如果增加新类型，则需要修改工厂，不符合OCP（开闭原则）的原则。
 * 简单工厂需要知道所有要生成的类型，当子类过多或者子类层次过多时不适合使用。
 * */

/**
 * VehicleInterface 车子接口
 */
interface VehicleInterface
{
    public function driveTo($destination);
}

//自行车类
class Bicycle implements VehicleInterface{
    public function driveTo($destination='')
    {
        // TODO: Implement driveTo() method.
        echo 'driveTo '.$destination;
    }
}

//摩托车类
class Scooter implements VehicleInterface{
    public function driveTo($destination='')
    {
        echo 'driveTo '.$destination;
    }
}

//工厂类
class ConcreteFactory{
    protected $typeList;
    /**
     *  可以在这里注入自己的车子类型
     */
    public function __construct()
    {
        $this->typeList = array(
            'bicycle' => __NAMESPACE__ . '\Bicycle',//自行车
            'scooter' => __NAMESPACE__ . '\Scooter',//摩托车
            //还可以增加电动车 等等
        );
    }

    /**
     * 创建车子
     */
    public function createVehicle($type)
    {
        if (!array_key_exists($type, $this->typeList)) {
            throw new \InvalidArgumentException("$type is not valid vehicle");
        }
        $className = $this->typeList[$type];

        return new $className();
    }
}

$factory = new ConcreteFactory();
$bicycle = $factory -> createVehicle('bicycle');
$bicycle -> driveTo('目的地');//利用自行车去目的地